package com.xingda.packing.dmds.rule;

import com.xingda.packing.dmds.common.RangeUtils;
import com.xingda.packing.dmds.domain.ProductBox;
import com.xingda.packing.dmds.domain.Wheel;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;

@Slf4j
public class RuleProb {
    private final static double p_sigma = 0.63;
    private final static int cache_capacity = 4;


    /**
     * 方差概率
     */
    public static double sigma_factor(ProductBox productBox, Wheel wheel) {
        double r_sigma = productBox.getPackDemand().getBoxDeviation().getMax().doubleValue();
        // 如果不启用 直接返回1
        if (!productBox.getPackDemand().getBoxDeviation().isEnable()) {
            return 1;
        }
        // 预放轮
        productBox.prePutWheel(wheel);
        // 要求整箱个数
        int drawing_num = productBox.getRequireCount();
        // 要求整箱层数
        int floorNum = productBox.getRequireFloorCount();
        // 要求每层数量
        int layer_cap = productBox.getFloorLocationCount();
        // 本箱子放置个数
        int boxCount = productBox.allCheckWheel().size();
        // 本层放置个数
        int floorCount = productBox.allCheckWheel().size() - (productBox.getNowFloorNum() - 1) * productBox.getFloorLocationCount();
        log.info("box:{}, wheel:{}, floor:{}, layer_cap:{}, boxCount:{}, floorCount:{}",
                productBox.getBoxNo(), wheel.getBarCode(), productBox.getCurrentPackFloorNo(), layer_cap, boxCount, floorCount);

        double sigma_factor;
        // 本层最后一个
        if (layer_cap - floorCount == 0) {
            // 如果是最后一层
            if (floorNum == productBox.getCurrentPackFloorNo()) {
                if (productBox.isBoxVarianceRange()) {
                    sigma_factor = 1;
                } else {
                    return 0;
                }
            } else {
                // 每个扭转值减去平均的平方和
                double pack_data_pow_sum = productBox.floorPowSum();
                double t_sigma_square = ((drawing_num - 1) * r_sigma * r_sigma - pack_data_pow_sum) / (drawing_num - boxCount);
                sigma_factor = RangeUtils.succeed_sigma_factor(Math.sqrt(t_sigma_square), p_sigma, drawing_num - boxCount, cache_capacity);
            }
        } else {
            double pack_data_pow_sum = productBox.floorPowSum();
            double t_sigma_square = ((drawing_num - 1) * r_sigma * r_sigma - pack_data_pow_sum) / (drawing_num - boxCount);
            sigma_factor = RangeUtils.succeed_sigma_factor(Math.sqrt(t_sigma_square), p_sigma, drawing_num - boxCount, cache_capacity);
        }
        productBox.clearPrePutWheel();
        return sigma_factor;
    }

    /**
     * 扭转和概率
     */
    public static double mu_factor(ProductBox productBox, Wheel wheel) {
        // 如果不启用 直接返回1
        if (!productBox.getPackDemand().getFloorTorsion().isEnable()) {
            return 1;
        }
        // 预放轮
        productBox.prePutWheel(wheel);
        double r_min = productBox.getPackDemand().getFloorTorsion().getMin().doubleValue();
        double r_max = productBox.getPackDemand().getFloorTorsion().getMax().doubleValue();
        double p_mu = (r_min + r_max) / 2 / productBox.getFloorLocationCount();
        // 要求每层数量
        int layer_cap = productBox.getFloorLocationCount();
        // 本层放置个数
        int floorCount = productBox.allCheckWheel().size() - (productBox.getNowFloorNum() - 1) * productBox.getFloorLocationCount();
        // 扭转可放概率
        double mu_factor;
        log.info("box:{}, wheel:{}, layer_cap:{}, floorCount:{}",productBox.getBoxNo(), wheel.getBarCode(), layer_cap, floorCount);
        // 本层最后一个
        if (layer_cap - floorCount == 0) {
            // 如果本层扭转和在范围内
            if (productBox.isFloorTorsionRange()) {
                mu_factor = 1;
            } else {
                return 0;
            }
        } else {
            double pack_data_sum = productBox.floorCheckWheel().stream().map(Wheel::getTorsionValue)
                    .mapToDouble(BigDecimal::doubleValue).sum();
            double t_min = (r_min - pack_data_sum) / (layer_cap - floorCount);
            double t_max = (r_max - pack_data_sum) / (layer_cap - floorCount);

            mu_factor = RangeUtils.succeed_mu_factor(t_min, t_max, p_mu, p_sigma, layer_cap - floorCount, cache_capacity);
        }
        productBox.clearPrePutWheel();
        return mu_factor;
    }

    /**
     * 调用方差和扭转计算概率方法返回概率结果
     */
    public static double prob_factor(ProductBox productBox, Wheel wheel) {
        // 方差概率
        double sigma_factor = 1.0;
        if (productBox.getPackDemand().getBoxDeviation().isEnable()) {
            sigma_factor = sigma_factor(productBox, wheel);
        }

        // 扭转和概率
        double mu_factor = 1.0;
        if (productBox.getPackDemand().getFloorTorsion().isEnable()) {
            mu_factor = mu_factor(productBox, wheel);
        }
        double prob_factor = sigma_factor * mu_factor;
        log.info("box:{}, wheel:{}, factor:{},sigma_factor:{}，mu_factor：{}", productBox.getBoxNo(), wheel.getBarCode(), prob_factor, sigma_factor, mu_factor);
        return prob_factor;
    }

}
